import { EventEmitter } from "@feng3d/event";
import { AnimationAction, AnimationBlendMode, AnimationMixer } from "../../thirdparty/three/imports";
import { Node3D } from "../core/Node3D";
import { AnimationAction3D } from "./AnimationAction3D";
import { AnimationClip3D } from "./AnimationClip3D";

export interface AnimationMixer3DEventMap
{
    loop: { action: AnimationAction3D, loopDelta: number }
    finished: { action: AnimationAction3D, loopDelta: number }
}

export class AnimationMixer3D extends EventEmitter<AnimationMixer3DEventMap>
{
    _animationMixer: AnimationMixer;

    model: Node3D;

    get timeScale()
    {
        return this._animationMixer.timeScale;
    }
    set timeScale(v)
    {
        this._animationMixer.timeScale = v;
    }

    constructor(model: Node3D)
    {
        super();
        this.model = model;
        this._animationMixer = new AnimationMixer(this.model._group);

        this._animationMixer.addEventListener("loop", this._onLoop);
        this._animationMixer.addEventListener("finished", this._onFinished);
    }

    destory()
    {
        this._animationMixer.removeEventListener("loop", this._onLoop);
        this._animationMixer.removeEventListener("finished", this._onFinished);

        this._animationMixer = null;
        this.model = null;
    }

    clipAction(clip: AnimationClip3D, root?: Node3D, blendMode?: AnimationBlendMode)
    {
        const action = this._animationMixer.clipAction(clip._animationClip, root?._group, blendMode);

        const animationAction = AnimationAction3D.get(action);

        return animationAction;
    }

    update(deltaTime: number)
    {
        this._animationMixer.update(deltaTime);
    }

    private _onLoop = (event: { type: "loop", target: AnimationMixer, action?: AnimationAction, loopDelta?: number }) =>
    {
        this.emit(event.type, { action: AnimationAction3D.get(event.action), loopDelta: event.loopDelta });
    };

    private _onFinished = (event: { type: "finished", target: AnimationMixer, action?: AnimationAction, loopDelta?: number }) =>
    {
        this.emit(event.type, { action: AnimationAction3D.get(event.action), loopDelta: event.loopDelta });
    };
}
